// app/service/plugin_data_service.js
'use strict';

const { Service } = require('egg');

class PluginDataService extends Service {
  // 处理插件发送的数据
  async processPluginData(pluginData) {
    const { ctx } = this;
    const { batchId, timestamp, dataType, data } = pluginData;
    
    try {
      // 记录处理开始时间
      const startTime = Date.now();
      ctx.logger.info(`[PluginData] 开始处理插件数据 - 批次ID: ${batchId}, 数据类型: ${dataType}, 条数: ${data.length}`);
      
      // 1. 数据安全验证
      const validatedData = this.validateAndSanitizeData(data, dataType);
      
      // 2. 数据初步验证和清洗
      const cleanedData = this.cleanAndValidateData(validatedData);
      
      // 3. 简单去重（基于请求URL和时间戳）
      const deduplicatedData = this.simpleDeduplication(cleanedData);
      
      // 4. 数据分类标记
      const categorizedData = this.categorizeData(deduplicatedData, dataType);
      
      // 5. 保存批次信息到数据库
      const batchRecord = await this.saveBatchInfo(batchId, dataType, categorizedData.length);
      
      // 6. 保存数据项到数据库
      await this.saveDataItems(batchId, categorizedData);
      
      // 7. 临时存储在Redis中（用于批量处理）
      await this.storeInRedis(batchId, categorizedData);
      
      // 8. 根据数据类型调用相应的服务处理
      if (dataType === 'invoice' || this.isInvoiceData(categorizedData)) {
        await this.processInvoiceData(categorizedData);
      } else if (dataType === 'sales_order' || dataType === 'purchase_order') {
        await this.processOrderData(categorizedData, dataType);
      } else if (dataType === 'bank') {
        await this.processBankDataForBatch(categorizedData);
      }
      
      // 9. 触发异步处理任务
      await this.triggerAsyncProcessing(batchId, dataType);
      
      const endTime = Date.now();
      const processingTime = endTime - startTime;
      
      // 更新批次处理时间
      await ctx.model.PluginDataBatchModel.update({
        processingTime: processingTime
      }, {
        where: { batchId: batchId }
      });
      
      ctx.logger.info(`[PluginData] 插件数据初步处理完成 - 批次ID: ${batchId}, 处理时间: ${processingTime}ms`);
      
      return {
        processedCount: categorizedData.length,
        processingTime: processingTime,
        batchId: batchId
      };
    } catch (error) {
      ctx.logger.error('[PluginData] 处理插件数据失败:', error);
      
      // 记录错误信息到批次记录
      await ctx.model.PluginDataBatchModel.update({
        status: 'failed',
        errorMessage: error.message
      }, {
        where: { batchId: batchId }
      });
      
      throw error;
    }
  }
  
  // 数据安全验证和清洗
  validateAndSanitizeData(data, dataType) {
    const { ctx } = this;
    
    // 验证数据是否为数组
    if (!Array.isArray(data)) {
      ctx.logger.warn('[PluginData] 数据不是数组格式，已拒绝');
      throw new Error('数据格式错误：必须为数组');
    }
    
    // 限制数据量，防止恶意大量数据
    if (data.length > 1000) {
      ctx.logger.warn(`[PluginData] 数据量过大 (${data.length})，已拒绝`);
      throw new Error('数据量过大：单次传输不得超过1000条');
    }
    
    // 验证数据类型
    const validDataTypes = ['bank', 'sales_order', 'purchase_order', 'invoice', 'incoming_invoice', 'outgoing_invoice', 'announcement', 'unknown'];
    if (dataType && !validDataTypes.includes(dataType)) {
      ctx.logger.warn(`[PluginData] 无效的数据类型: ${dataType}`);
      throw new Error(`无效的数据类型: ${dataType}`);
    }
    
    // 对每条数据进行安全验证
    const sanitizedData = [];
    for (const item of data) {
      // 验证必要字段
      if (!item || typeof item !== 'object') {
        ctx.logger.warn('[PluginData] 数据项格式错误，跳过');
        continue;
      }
      
      // 验证URL格式
      if (item.url && typeof item.url !== 'string') {
        ctx.logger.warn('[PluginData] URL格式错误，跳过');
        continue;
      }
      
      // 验证HTTP方法
      if (item.method && typeof item.method !== 'string') {
        ctx.logger.warn('[PluginData] HTTP方法格式错误，跳过');
        continue;
      }
      
      // 验证时间戳
      if (item.timestamp) {
        // 如果是字符串格式的时间戳，尝试转换为数字
        if (typeof item.timestamp === 'string') {
          // 检查是否为ISO格式的时间字符串
          if (item.timestamp.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)) {
            // 转换为时间戳毫秒数
            const timestampNum = new Date(item.timestamp).getTime();
            if (isNaN(timestampNum) || timestampNum < 0) {
              ctx.logger.warn('[PluginData] 时间戳格式错误，跳过');
              continue;
            }
            // 更新item.timestamp为数字格式
            item.timestamp = timestampNum;
          } else {
            // 尝试直接转换为数字
            const timestampNum = Number(item.timestamp);
            if (isNaN(timestampNum) || timestampNum < 0) {
              ctx.logger.warn('[PluginData] 时间戳格式错误，跳过');
              continue;
            }
            item.timestamp = timestampNum;
          }
        } else if (typeof item.timestamp !== 'number' || item.timestamp < 0) {
          ctx.logger.warn('[PluginData] 时间戳格式错误，跳过');
          continue;
        }
      }
      
      // 限制URL长度，防止恶意超长URL
      if (item.url && item.url.length > 2000) {
        ctx.logger.warn('[PluginData] URL过长，跳过');
        continue;
      }
      
      // 限制请求和响应数据大小
      let requestData = item.request;
      if (item.request && typeof item.request === 'object') {
        const requestStr = JSON.stringify(item.request);
        if (requestStr.length > 100000) { // 100KB限制
          ctx.logger.warn('[PluginData] 请求数据过大，跳过');
          continue;
        }
      }
      
      let responseData = item.response;
      if (item.response && typeof item.response === 'object') {
        const responseStr = JSON.stringify(item.response);
        if (responseStr.length > 1000000) { // 1MB限制
          ctx.logger.warn('[PluginData] 响应数据过大，跳过');
          continue;
        }
      }
      
      // 数据脱敏处理
      const sanitizedItem = {
        ...item,
        // 清理敏感字段
        request: this.sanitizeSensitiveData(requestData),
        response: this.sanitizeSensitiveData(responseData),
        ruleInfo: item.ruleInfo || {}
      };
      
      sanitizedData.push(sanitizedItem);
    }
    
    ctx.logger.info(`[PluginData] 数据安全验证完成，原始数据: ${data.length}条，验证后数据: ${sanitizedData.length}条`);
    return sanitizedData;
  }
  
  // 敏感数据脱敏
  sanitizeSensitiveData(data) {
    if (!data || typeof data !== 'object') {
      return data;
    }
    
    // 深拷贝数据以避免修改原始数据
    const sanitized = JSON.parse(JSON.stringify(data));
    
    // 定义敏感字段
    const sensitiveFields = [
      'password', 'token', 'authorization', 'auth', 'secret', 
      'key', 'certificate', 'privateKey', 'accessKey', 'secretKey',
      'idCard', 'bankCard', 'phone', 'mobile', 'email',
      'account', 'username', 'credential'
    ];
    
    // 递归处理对象
    const sanitizeObject = (obj) => {
      if (!obj || typeof obj !== 'object') {
        return obj;
      }
      
      if (Array.isArray(obj)) {
        return obj.map(item => sanitizeObject(item));
      }
      
      const result = {};
      for (const [key, value] of Object.entries(obj)) {
        // 检查字段名是否包含敏感词
        const lowerKey = key.toLowerCase();
        const isSensitive = sensitiveFields.some(field => 
          lowerKey.includes(field) || 
          lowerKey.includes(field.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()) // 驼峰转下划线
        );
        
        if (isSensitive) {
          // 对敏感字段进行脱敏处理
          result[key] = '***';
        } else if (typeof value === 'object' && value !== null) {
          // 递归处理嵌套对象
          result[key] = sanitizeObject(value);
        } else {
          result[key] = value;
        }
      }
      
      return result;
    };
    
    return sanitizeObject(sanitized);
  }
  
  // 检查是否为发票数据
  isInvoiceData(dataItems) {
    if (!Array.isArray(dataItems) || dataItems.length === 0) {
      return false;
    }
    
    // 检查第一个数据项是否为发票数据
    const firstItem = dataItems[0];
    if (firstItem.category === 'invoice' || firstItem.category === 'incoming_invoice' || firstItem.category === 'outgoing_invoice') {
      return true;
    }
    
    // 根据URL判断
    if (firstItem.url) {
      if (firstItem.url.includes('queryFpjcxx') || firstItem.url.includes('qlfpcx')) {
        return true;
      }
      if (firstItem.url.includes('queryFpxx') || firstItem.url.includes('fpxxcx')) {
        return true;
      }
    }
    
    return false;
  }
  
  // 处理发票数据
  async processInvoiceData(dataItems) {
    const { ctx } = this;
    
    try {
      // 获取发票服务
      const outgoingInvoiceService = ctx.service.outgoingInvoiceService;
      const incomingInvoiceService = ctx.service.incomingInvoiceService;
      
      // 处理每个发票数据项
      for (const item of dataItems) {
        if (item.category === 'invoice' || item.category === 'outgoing_invoice') {
          ctx.logger.info('[PluginData] 开始处理销项发票数据:', item.url);
          
          // 调用销项发票服务处理数据
          const result = await outgoingInvoiceService.extractInvoiceFromPluginData(item);
          
          if (result && result.success) {
            ctx.logger.info(`[PluginData] 销项发票数据处理成功 - 处理数量: ${result.invoiceCount}`);
          } else if (result) {
            ctx.logger.warn('[PluginData] 销项发票数据处理失败:', result.error);
          }
        } else if (item.category === 'incoming_invoice') {
          ctx.logger.info('[PluginData] 开始处理进项发票数据:', item.url);
          
          // 调用进项发票服务处理数据
          const result = await outgoingInvoiceService.extractIncomingInvoiceFromPluginData(item);
          
          if (result && result.success) {
            ctx.logger.info(`[PluginData] 进项发票数据处理成功 - 处理数量: ${result.invoiceCount}`);
          } else if (result) {
            ctx.logger.warn('[PluginData] 进项发票数据处理失败:', result.error);
          }
        }
      }
    } catch (error) {
      ctx.logger.error('[PluginData] 处理发票数据失败:', error);
      throw error;
    }
  }
  
  // 处理订单数据
  async processOrderData(dataItems, orderType) {
    const { ctx } = this;
    
    try {
      // 获取销售订单服务
      const salesOrderService = ctx.service.salesOrderService;
      // 获取采购订单服务
      const purchaseOrderService = ctx.service.purchaseOrderService;
      
      // 处理每个订单数据项
      for (const item of dataItems) {
        if (orderType === 'sales_order') {
          ctx.logger.info('[PluginData] 开始处理销售订单数据:', item.url);
          
          // 这里可以调用销售订单服务处理数据
          // 目前我们只是记录日志，实际项目中需要实现具体的处理逻辑
          ctx.logger.info('[PluginData] 销售订单数据已接收，等待进一步处理');
        } else if (orderType === 'purchase_order') {
          ctx.logger.info('[PluginData] 开始处理采购订单数据:', item.url);
          
          // 采购订单处理逻辑
          const result = await purchaseOrderService.extractPurchaseOrderFromPluginData(item);
          
          if (result && result.success) {
            ctx.logger.info(`[PluginData] 采购订单数据处理成功 - 处理数量: ${result.orderCount}`);
          } else if (result) {
            ctx.logger.warn('[PluginData] 采购订单数据处理失败:', result.error);
          }
        }
      }
    } catch (error) {
      ctx.logger.error('[PluginData] 处理订单数据失败:', error);
      throw error;
    }
  }
  
  // 保存批次信息到数据库
  async saveBatchInfo(batchId, dataType, count) {
    const { ctx } = this;
    
    try {
      const [batchRecord, created] = await ctx.model.PluginDataBatchModel.findOrCreate({
        where: { batchId: batchId },
        defaults: {
          batchId: batchId,
          dataType: dataType,
          count: count,
          status: 'pending',
          processedCount: 0,
          failedCount: 0,
          createdAt: new Date(),
          updatedAt: new Date()
        }
      });
      
      if (!created) {
        // 如果批次已存在，更新状态
        await ctx.model.PluginDataBatchModel.update({
          status: 'pending',
          count: count,
          updatedAt: new Date()
        }, {
          where: { batchId: batchId }
        });
      }
      
      return batchRecord;
    } catch (error) {
      ctx.logger.error('[PluginData] 保存批次信息失败:', error);
      throw error;
    }
  }
  
  // 保存数据项到数据库
  async saveDataItems(batchId, dataItems) {
    const { ctx } = this;
    
    try {
      const itemsToSave = dataItems.map(item => ({
        itemId: item.id,
        batchId: batchId,
        url: item.url,
        method: item.method,
        category: item.category,
        status: item.status,
        requestData: item.request,
        responseData: item.response,
        ruleInfo: item.ruleInfo,
        createdAt: new Date(),
        updatedAt: new Date()
      }));
      
      // 批量插入数据项
      await ctx.model.PluginDataItemModel.bulkCreate(itemsToSave, {
        ignoreDuplicates: true // 忽略重复项
      });
      
      ctx.logger.info(`[PluginData] 数据项保存完成 - 批次ID: ${batchId}, 条数: ${itemsToSave.length}`);
    } catch (error) {
      ctx.logger.error('[PluginData] 保存数据项失败:', error);
      throw error;
    }
  }
  
  // 数据初步验证和清洗
  cleanAndValidateData(data) {
    const { ctx } = this;
    const cleanedData = [];
    
    for (const item of data) {
      // 验证必要字段
      if (!item.url || !item.method || !item.timestamp) {
        ctx.logger.warn('[PluginData] 数据项缺少必要字段，跳过:', item);
        continue;
      }
      
      // 清洗数据
      const cleanedItem = {
        id: item.id || this.generateUniqueId(),
        url: item.url.trim(),
        method: item.method.toUpperCase(),
        timestamp: item.timestamp,
        request: item.request || {},
        response: item.response || {},
        ruleInfo: item.ruleInfo || {},
        // 添加处理时间戳
        processedAt: new Date().toISOString()
      };
      
      cleanedData.push(cleanedItem);
    }
    
    return cleanedData;
  }
  
  // 简单去重（基于请求URL和时间戳）
  simpleDeduplication(data) {
    const seen = new Set();
    const uniqueData = [];
    
    for (const item of data) {
      // 创建唯一标识符（URL + 时间戳）
      const key = `${item.url}_${item.timestamp}`;
      
      if (!seen.has(key)) {
        seen.add(key);
        uniqueData.push(item);
      }
    }
    
    return uniqueData;
  }
  
  // 数据分类标记
  categorizeData(data, dataType) {
    return data.map(item => {
      // 根据数据类型添加分类标记
      let category = 'unknown';
      
      if (dataType) {
        category = dataType;
      } else if (item.ruleInfo && item.ruleInfo.dataType) {
        category = item.ruleInfo.dataType;
      } else if (item.url) {
        // 根据URL模式自动分类
        if (item.url.includes('bank') || item.url.includes('transaction')) {
          category = 'bank';
        } else if (item.url.includes('purchase') && item.url.includes('order')) {
          category = 'purchase_order'; // 采购订单
        } else if (item.url.includes('order') || item.url.includes('mall')) {
          category = 'sales_order'; // 销售订单
        } else if (item.url.includes('qlfpcx')) {
          // 进项发票查询接口
          category = 'incoming_invoice';
        } else if (item.url.includes('fpxxcx')) {
          // 销项发票查询接口
          category = 'outgoing_invoice';
        } else if (item.url.includes('invoice') || item.url.includes('fpjcxx')) {
          category = 'invoice';
        }
      }
      
      return {
        ...item,
        category: category,
        // 添加处理状态
        status: 'pending' // pending, processed, failed
      };
    });
  }
  
  // 临时存储在Redis中
  async storeInRedis(batchId, data) {
    const { ctx } = this;
    
    try {
      // 将数据存储到Redis中，等待批量处理
      const key = `plugin_data_batch:${batchId}`;
      const value = JSON.stringify(data);
      
      // 设置过期时间（24小时）
      await ctx.app.redis.set(key, value, 'EX', 24 * 60 * 60);
      
      // 更新批次信息
      const batchInfoKey = `plugin_data_batch_info:${batchId}`;
      const batchInfo = {
        batchId: batchId,
        count: data.length,
        createdAt: new Date().toISOString(),
        status: 'stored'
      };
      
      await ctx.app.redis.set(batchInfoKey, JSON.stringify(batchInfo), 'EX', 24 * 60 * 60);
      
      ctx.logger.info(`[PluginData] 数据已存储到Redis - 批次ID: ${batchId}, 条数: ${data.length}`);
    } catch (error) {
      ctx.logger.error('[PluginData] 存储数据到Redis失败:', error);
      throw error;
    }
  }
  
  // 触发异步处理任务
  async triggerAsyncProcessing(batchId, dataType) {
    const { ctx } = this;
    
    try {
      // 更新批次状态为处理中
      await ctx.model.PluginDataBatchModel.update({
        status: 'processing'
      }, {
        where: { batchId: batchId }
      });
      
      // 发送消息到消息队列，触发深度处理
      // 这里我们使用Egg.js的定时任务来模拟异步处理
      ctx.logger.info(`[PluginData] 触发异步处理任务 - 批次ID: ${batchId}, 数据类型: ${dataType}`);
      
      // 实际项目中这里会发送到消息队列（如RabbitMQ、Kafka等）
      // 暂时记录日志，后续可以通过定时任务或消息队列处理
    } catch (error) {
      ctx.logger.error('[PluginData] 触发异步处理任务失败:', error);
    }
  }
  
  // 查询数据处理状态
  async getDataProcessingStatus(batchId) {
    const { ctx } = this;
    
    try {
      // 首先从数据库查询批次信息
      const batchRecord = await ctx.model.PluginDataBatchModel.findOne({
        where: { batchId: batchId }
      });
      
      if (!batchRecord) {
        // 如果数据库中没有，尝试从Redis查询
        const batchInfoKey = `plugin_data_batch_info:${batchId}`;
        const batchInfoStr = await ctx.app.redis.get(batchInfoKey);
        
        if (!batchInfoStr) {
          return {
            batchId: batchId,
            status: 'not_found',
            message: '批次不存在或已过期'
          };
        }
        
        const batchInfo = JSON.parse(batchInfoStr);
        
        return {
          batchId: batchInfo.batchId,
          count: batchInfo.count,
          createdAt: batchInfo.createdAt,
          status: batchInfo.status,
          message: '批次信息查询成功'
        };
      }
      
      // 从数据库返回信息
      return {
        batchId: batchRecord.batchId,
        dataType: batchRecord.dataType,
        count: batchRecord.count,
        status: batchRecord.status,
        processedCount: batchRecord.processedCount,
        failedCount: batchRecord.failedCount,
        processingTime: batchRecord.processingTime,
        createdAt: batchRecord.createdAt,
        updatedAt: batchRecord.updatedAt,
        completedAt: batchRecord.completedAt,
        message: '批次信息查询成功'
      };
    } catch (error) {
      ctx.logger.error('[PluginData] 查询数据处理状态失败:', error);
      throw error;
    }
  }
  
  // 获取数据统计信息
  async getDataStatistics() {
    const { ctx } = this;
    
    try {
      // 获取批次统计信息
      const batchStats = await ctx.model.PluginDataBatchModel.findAndCountAll({
        attributes: [
          'status',
          [ctx.app.Sequelize.fn('COUNT', ctx.app.Sequelize.col('id')), 'count']
        ],
        group: ['status']
      });
      
      // 获取今日批次统计
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      
      const todayBatchCount = await ctx.model.PluginDataBatchModel.count({
        where: {
          createdAt: {
            [ctx.app.Sequelize.Op.gte]: today
          }
        }
      });
      
      // 获取数据分类统计
      const categoryStats = await ctx.model.PluginDataItemModel.findAndCountAll({
        attributes: [
          'category',
          [ctx.app.Sequelize.fn('COUNT', ctx.app.Sequelize.col('id')), 'count']
        ],
        group: ['category']
      });
      
      // 获取今日数据项统计
      const todayItemCount = await ctx.model.PluginDataItemModel.count({
        where: {
          createdAt: {
            [ctx.app.Sequelize.Op.gte]: today
          }
        }
      });
      
      // 计算总批次数
      let totalBatches = 0;
      if (Array.isArray(batchStats.rows)) {
        totalBatches = batchStats.rows.reduce((sum, item) => {
          return sum + (parseInt(item.get('count')) || 0);
        }, 0);
      }
      
      // 计算总记录数
      let totalRecords = 0;
      if (Array.isArray(categoryStats.rows)) {
        totalRecords = categoryStats.rows.reduce((sum, item) => {
          return sum + (parseInt(item.get('count')) || 0);
        }, 0);
      }
      
      return {
        totalBatches: totalBatches,
        totalRecords: totalRecords,
        todayBatches: todayBatchCount,
        todayRecords: todayItemCount,
        batchByStatus: batchStats.rows.map(item => ({
          status: item.get('status'),
          count: parseInt(item.get('count')) || 0
        })),
        dataByCategory: categoryStats.rows.map(item => ({
          category: item.get('category'),
          count: parseInt(item.get('count')) || 0
        }))
      };
    } catch (error) {
      ctx.logger.error('[PluginData] 获取数据统计信息失败:', error);
      throw error;
    }
  }
  
  // 处理银行流水数据（批量处理）
  async processBankDataForBatch(dataItems) {
    const { ctx } = this;
    
    try {
      // 处理每个银行流水数据项
      for (const item of dataItems) {
        ctx.logger.info('[PluginData] 开始处理银行流水数据:', item.url);
        
        // 调用银行流水处理方法
        const result = await this.processBankData(item);
        
        if (result && result.success) {
          ctx.logger.info(`[PluginData] 银行流水数据处理成功 - 处理数量: ${result.transactionCount}`);
          
          // 更新数据项状态
          await ctx.model.PluginDataItemModel.update({
            status: 'processed',
            processedAt: new Date()
          }, {
            where: { itemId: item.id }
          });
        } else if (result) {
          ctx.logger.warn('[PluginData] 银行流水数据处理失败:', result.error);
          
          // 更新数据项状态为失败
          await ctx.model.PluginDataItemModel.update({
            status: 'failed',
            errorMessage: result.error,
            processedAt: new Date()
          }, {
            where: { itemId: item.id }
          });
        }
      }
    } catch (error) {
      ctx.logger.error('[PluginData] 处理银行流水数据失败:', error);
      throw error;
    }
  }
  
  // 处理银行流水数据
  async processBankData(item) {
    const { ctx } = this;
    
    try {
      ctx.logger.info('[PluginData] 开始处理银行流水数据:', item.url);
      
      // 解析银行流水数据
      const bankTransactions = this.extractBankTransactionsFromPluginData(item);
      
      if (!bankTransactions || bankTransactions.length === 0) {
        ctx.logger.warn('[PluginData] 未提取到银行流水数据');
        return { success: false, error: '未提取到银行流水数据' };
      }
      
      // 批量保存银行流水数据
      const savedTransactions = [];
      let savedCount = 0;
      
      for (const transaction of bankTransactions) {
        try {
          // 检查是否已存在相同的流水记录
          const existing = await ctx.model.BankTransactionModel.findOne({
            where: {
              transactionId: transaction.transactionId,
              amount: transaction.amount,
              transactionDate: transaction.transactionDate
            }
          });
          
          if (existing) {
            ctx.logger.info(`[PluginData] 银行流水已存在，跳过: ${transaction.transactionId}`);
            continue;
          }
          
          // 保存新的银行流水记录
          const savedItem = await ctx.model.BankTransactionModel.create({
            ...transaction,
            importBatch: item.batchId,
            dataSource: 'plugin_capture',
            organizationId: 1 // 默认组织ID
          });
          
          savedTransactions.push(savedItem);
          savedCount++;
        } catch (saveError) {
          ctx.logger.error(`[PluginData] 保存银行流水失败: ${transaction.transactionId}`, saveError);
        }
      }
      
      ctx.logger.info(`[PluginData] 银行流水数据处理完成 - 成功保存: ${savedCount} 条`);
      
      return {
        success: true,
        transactionCount: savedCount
      };
    } catch (error) {
      ctx.logger.error('[PluginData] 处理银行流水数据失败:', error);
      return { success: false, error: error.message };
    }
  }
  
  // 从插件数据中提取银行流水
  extractBankTransactionsFromPluginData(item) {
    const { ctx } = this;
    
    try {
      // 检查数据结构
      if (!item || !item.response || !item.response.data) {
        ctx.logger.warn('[PluginData] 插件数据格式不正确，缺少response.data');
        return [];
      }
      
      const responseData = item.response.data;
      
      // 检查是否为杭州银行流水数据格式
      if (!responseData.data || !Array.isArray(responseData.data)) {
        ctx.logger.warn('[PluginData] 银行流水数据格式不正确，缺少data数组');
        return [];
      }
      
      // 提取银行流水数据
      const transactions = responseData.data.map(bankItem => {
        // 判断是收入还是支出
        const debitAmount = parseFloat(bankItem.debitAmount) || 0;  // 借方金额（支出）
        const loanAmount = parseFloat(bankItem.loanAmount) || 0;    // 贷方金额（收入）
        
        // 如果借方金额大于0，表示支出；如果贷方金额大于0，表示收入
        const amount = debitAmount > 0 ? -debitAmount : loanAmount;
        
        // 清理银行名称中的多余空格
        const cleanBankName = bankItem.organName ? bankItem.organName.replace(/\s+/g, '') : '';
        
        return {
          // 基本字段
          transactionId: bankItem.orderFlowNo,                    // 流水号
          payerName: bankItem.recAccountName,                     // 对方户名
          payerAccount: bankItem.recAccount,                      // 对方账号
          amount: amount,                                         // 交易金额
          transactionDate: bankItem.transferDate,                 // 交易日期
          transactionTime: `${bankItem.transferDate} ${bankItem.transferTime}`, // 交易时间
          balance: parseFloat(bankItem.balance) || 0,             // 余额
          remark: `${bankItem.summary}${bankItem.memo ? ` - ${bankItem.memo}` : ''}`, // 备注
          
          // 新增字段
          bankName: cleanBankName,                                // 银行名称（已清理空格）
          currency: bankItem.currencyTypeHZ,                      // 币种
          channel: bankItem.channelCode,                          // 渠道
          fee: parseFloat(bankItem.tranFee) || 0,                 // 手续费
          accountName: responseData.accountName,                  // 己方账户名称
          accountNumber: responseData.accountNo                   // 己方账户号码
        };
      });
      
      ctx.logger.info(`[PluginData] 成功提取 ${transactions.length} 条银行流水数据`);
      return transactions;
    } catch (error) {
      ctx.logger.error('[PluginData] 提取银行流水数据失败:', error);
      return [];
    }
  }

  // 生成唯一ID
  generateUniqueId() {
    return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  // 重新处理数据项
  async reprocessDataItem(item) {
    const { ctx } = this;
    
    try {
      ctx.logger.info(`[PluginData] 开始重新处理数据项: ${item.itemId}`);
      
      // 更新数据项状态为处理中
      await ctx.model.PluginDataItemModel.update({
        status: 'pending',
        errorMessage: null,
        processedAt: null
      }, {
        where: { itemId: item.itemId }
      });
      
      // 根据数据类型调用相应的处理方法
      if (item.category === 'bank') {
        const result = await this.processBankData(item);
        if (result && result.success) {
          // 更新数据项状态为已处理
          await ctx.model.PluginDataItemModel.update({
            status: 'processed',
            processedAt: new Date()
          }, {
            where: { itemId: item.itemId }
          });
          return { success: true, message: '银行流水数据重新处理成功' };
        } else {
          // 更新数据项状态为失败
          await ctx.model.PluginDataItemModel.update({
            status: 'failed',
            errorMessage: result ? result.error : '处理失败',
            processedAt: new Date()
          }, {
            where: { itemId: item.itemId }
          });
          return { success: false, message: '银行流水数据重新处理失败', error: result ? result.error : '处理失败' };
        }
      } else if (item.category === 'sales_order' || item.category === 'purchase_order') {
        // 处理订单数据
        if (item.category === 'purchase_order') {
          // 采购订单处理逻辑
          const result = await ctx.service.purchaseOrderService.extractPurchaseOrderFromPluginData(item);
          if (result && result.success) {
            await ctx.model.PluginDataItemModel.update({
              status: 'processed',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: true, message: '采购订单数据重新处理成功' };
          } else {
            await ctx.model.PluginDataItemModel.update({
              status: 'failed',
              errorMessage: result ? result.error : '处理失败',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: false, message: '采购订单数据重新处理失败', error: result ? result.error : '处理失败' };
          }
        } else {
          await ctx.model.PluginDataItemModel.update({
            status: 'processed',
            processedAt: new Date()
          }, {
            where: { itemId: item.itemId }
          });
          return { success: true, message: '订单数据重新处理成功' };
        }
      } else if (item.category === 'invoice' || item.category === 'incoming_invoice' || item.category === 'outgoing_invoice') {
        // 处理发票数据
        if (item.category === 'incoming_invoice') {
          const result = await ctx.service.outgoingInvoiceService.extractIncomingInvoiceFromPluginData(item);
          if (result && result.success) {
            await ctx.model.PluginDataItemModel.update({
              status: 'processed',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: true, message: '进项发票数据重新处理成功' };
          } else {
            await ctx.model.PluginDataItemModel.update({
              status: 'failed',
              errorMessage: result ? result.error : '处理失败',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: false, message: '进项发票数据重新处理失败', error: result ? result.error : '处理失败' };
          }
        } else {
          const result = await ctx.service.outgoingInvoiceService.extractInvoiceFromPluginData(item);
          if (result && result.success) {
            await ctx.model.PluginDataItemModel.update({
              status: 'processed',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: true, message: '销项发票数据重新处理成功' };
          } else {
            await ctx.model.PluginDataItemModel.update({
              status: 'failed',
              errorMessage: result ? result.error : '处理失败',
              processedAt: new Date()
            }, {
              where: { itemId: item.itemId }
            });
            return { success: false, message: '销项发票数据重新处理失败', error: result ? result.error : '处理失败' };
          }
        }
      } else {
        // 其他类型数据
        await ctx.model.PluginDataItemModel.update({
          status: 'processed',
          processedAt: new Date()
        }, {
          where: { itemId: item.itemId }
        });
        return { success: true, message: '数据重新处理成功' };
      }
    } catch (error) {
      ctx.logger.error('[PluginData] 重新处理数据项失败:', error);
      
      // 更新数据项状态为失败
      await ctx.model.PluginDataItemModel.update({
        status: 'failed',
        errorMessage: error.message,
        processedAt: new Date()
      }, {
        where: { itemId: item.itemId }
      });
      
      return { success: false, message: '数据重新处理失败', error: error.message };
    }
  }
}

module.exports = PluginDataService;